#include <bits/stdc++.h>
using namespace std;

//经过下面的测试，可以发现，异常是一层一层栈帧的寻找，找不到就退出当前栈帧，当前定义的局部变量也会销毁，其后续的代码也不再执行
//实际上到main函数都没找到接受异常的，总体就是异常无法处理，程序就会退出。
class A
{
    public:
    ~A()
    {
        cout<<"~A\n";
    }
};

double Exception_divise_zero(int a,int factor)
{
    if(factor==0)
    {
        throw "Division by zero condition";//抛出什么类型，接受什么类型，不允许有任何的不同，否则异常就无法被接受,但是基类和派生类之间，基类接受派生类是可行的
        //如这里是const char*,那接受就必须是const char* ,少了const或者用const string都不行
    }
    else
    {
        return (double)a/factor;
    }
}

void CallDivision()
{
    A b;//但是可以发现，在一层层处理当前栈帧的时候，会销毁这时候定义的局部变量
    Exception_divise_zero(10,0);
    A a;//经过测验可以发现，抛异常之后，之后的代码不会再执行了
}


void Test_Exception(){
    try
    {
        CallDivision();
    }
    catch(const char* e)
    {
        std::cerr << e<< '\n';
    }
    catch(...)//可以接受任何异常，下面一般写未知异常，这样的话，就能避免直接杀死程序
    {
        cerr<<"unkown Exception \n";
    }
}   


//异常可以用父类接受子类

class MyExeception{
    protected:
    int _eid;
    string _errorMsg;
    public:
    MyExeception(int eid,string eMsg)
    :_eid(eid)
    ,_errorMsg(eMsg)
    {

    }
    virtual string what()const
    {
        return "eid::"+to_string(_eid)+"\n"+"eMsg::"+_errorMsg;
    }
};

class net_serve_exceoptin: public MyExeception{
    string Mysign;
    public:
    net_serve_exceoptin(int eid,string eMsg)
    :MyExeception(eid,eMsg)
    ,Mysign("网络错误")
    {
        ;
    }
};


int Test()
{
    throw net_serve_exceoptin(1,"net error");
    return 0;
}

int main()
{
    while(1)
    {
        try
        {
            Test();
        }
        catch(MyExeception e)
        {
            std::cerr << e.what() << '\n';
        }
        catch (...)
        {
            cout << "Unkown Exception" << endl;
        }
    }
    return 0;
}

//--------------------------------------------------------


double Division(int a,int factor)
{
    if(factor==0)
    {
        throw "Division by zero condition";
    }
    else
    {
        return (double)a/factor;
    }
}

void Exception_Newdelete()
{
    int *arr = new int[10];
    //Division(10,0);//这个Division的函数，抛出一场之后，由于当前函数没有，接受的，后面代码不执行，显然会导致内存错误
    //----------------------------------------------------
    //解决方法一，重新抛出，但是解决的问题十分受限，本质并没有解决完.倘若有调用多个函数，各自又都开辟后续的空间在该处异常之后释放，显然会导致大量的问题
    try{
        Division(10,0);
    }
    catch(const char* e)
    {
        delete[]arr;
        arr = nullptr;
        //重新再次抛出
        throw "Division error";
    }
    catch(...)//捕获什么异常，抛出什么异常
    {
        delete[]arr;
        arr = nullptr;
        throw;
    }
    //因此另外的解决方法就是智能指针
    delete[] arr;   
}

void Exception_get()
{
    try{
        Exception_Newdelete();
    }
    catch(const char* e)
    {
        cerr<<e<<endl;
    }
}
// int main()
// {
//     Exception_get();
//     return 0;
// }